# coding=utf8
# __author__ = 'MoaiStone'
import ijson.backends.yajl2_cffi as ijson
import os
import fiona
import copy
import gc
import sys
import zipfile


class times():
    ''' 循环计数器，达到一定次数返回True，并执行回调函数'''

    def __init__(self, count, func=None):
        self.count = count
        self.now = 1
        self.func = func

    def addOne(self):
        if self.now >= self.count:
            if self.func:
                self.func()
            self.now = 2
            return True
        else:
            self.now += 1
            return False


def _jsonfile2FGDB(f, outgdb, fcName):
    ''' 根据具体的Json格式需要做调整'''
    schema = {'geometry': 'Polygon', 'properties': {}}  # 要素类的字段可以为空
    gc.disable()    # 关闭gc，每10W条记录手动执行一次
    objects = ijson.items(f, 'features.item')
    with fiona.open(outgdb, 'w', driver='FileGDB', layer=fcName, schema=schema, crs='EPSG:4326') as cur:
        t_records, t_gc, records = times(1000), times(100, gc.collect), []
        for row in objects:
            if t_records.addOne():
                cur.writerecords(records)   # 达到一定条数，一次导入一批
                records = []
                t_gc.addOne()   # 达到一定次数执行gc
            newrow = copy.copy(schema)      # 构建一条记录
            newrow['geometry'] = row['geometry']
            records.append(newrow)
        cur.writerecords(records)   # 导入最后剩余的一批
    gc.enable()


def JsonFile2FGDB(jsonFile, outgdb):
    ''' 将Json格式的数据文件转换成FileGDB要素类，支持超大json文件，支持直读zip'''
    if zipfile.is_zipfile(jsonFile):
        with zipfile.ZipFile(jsonFile) as zf:
            for _zfile in zf.namelist():
                if _zfile.endswith(("/", "\\")):
                    continue
                fcName = os.path.basename(_zfile).split('.')[0]
                with zf.open(_zfile) as f:
                    _jsonfile2FGDB(f, outgdb, fcName)
    else:
        fcName = os.path.basename(jsonFile).split('.')[0]
        with open(jsonFile, 'rb') as f:
            _jsonfile2FGDB(f, outgdb, fcName)


if __name__ == '__main__':
    # 输入json格式的文件，和输出路径，输出位置如果存在gdb会覆盖同名的要素类，不会删除整个gdb
    JsonFile2FGDB("TestData.json", "new.gdb")
    JsonFile2FGDB("TestData.zip", "new1.gdb")
